/**
 * @brief 日志组件，将程序的运行过程记录下来，方便后期排错
*/

#pragma once

#include <iostream>
#include <cstring>
#include <ctime>
#include <cstdio>
#include <cstdarg>
#include <cassert>
#include <unistd.h>

#define LOG_MESSAGE_SIZE 2048

enum {
    DEBUG,
    NORMAL,
    WARNING,
    ERROR,
    FATAL
};

// 将日志等级从整形(枚举类型)转为字符串
const char* levelToString(int level) {
    switch (level) {
        case DEBUG: return "DEBUG";
        case NORMAL: return "NORMAL";
        case WARNING: return "WARNING";
        case ERROR: return "ERROR";
        case FATAL: return "FATAL";
        default: return "NO THIS LEVEL";
    }
}  

/**
 * @param level 日志等级
 * @param format 可变参数列表，类似于printf的用法，可以有至少0个占位符
*/
void logMessage(int level, const char* format, ...) {
    //* log_message: [日志等级] [时间] [pid] [message]

    // 设计日志信息前缀
    char log_prefix[LOG_MESSAGE_SIZE] = {};
    time_t raw_time = time(nullptr);
    struct tm* time_info = localtime(&raw_time);
    char* time_str = asctime(time_info);
    time_str[strlen(time_str) - 1] = '\0'; // 去掉asctime自带的换行符
    snprintf(log_prefix, LOG_MESSAGE_SIZE, "[%s][%s][pid: %d]", 
        levelToString(level), time_str, getpid());

    // 设置日志信息正文
    char log_content[LOG_MESSAGE_SIZE] = {};
    va_list arg;
    va_start(arg, format); // 将arg指针定位到可变参数列表
    vsnprintf(log_content, LOG_MESSAGE_SIZE, format, arg);

    // 将日志信息输出到屏幕
    std::cout << log_prefix << " " << log_content << std::endl;
}